/*
  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  PARTICULAR PURPOSE.

  Copyright (c) 2009 PRO ACTIVE SAS - www.proactive-group.com
   
  Ref_Find.c
  -------------

  This is the reference applications that shows how to poll the reader,
  showing each incoming tag identifier
  
  LTX 25/08/2009 : initial release

*/
#include "products/springprox/springprox.h"

#ifdef WIN32
#include <conio.h>              /* For kbhit and getch */
#endif
#ifdef __linux
#include <unistd.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv)
{
  SWORD rc;
  int i;
  char s_buffer[64];
  BYTE uid[12];
  BYTE uid_len = 12;
  DWORD features;
  WORD proto = 0;

  char *device = NULL;

  if (argc > 1)
    device = argv[1];

  printf("SpringCard SDK for K531/SpringProx-CF/CSB Legacy\n");
  printf("\n");
  printf("FIND : multi-protocol card polling reference demo\n");
  printf("----------------------------------------------------\n");
  printf("www.springcard.com\n\n");

  /* Open reader */
  /* ----------- */

  rc = SPROX_GetLibrary(s_buffer, sizeof(s_buffer));
  if (rc != MI_OK)
  {
    printf("Failed to get API version\n");
    goto done;
  }
  printf("API version : %s\n", s_buffer);
  printf("\n");

  /* Open reader */
  /* ----------- */

  rc = SPROX_ReaderOpen(device);
  if (rc != MI_OK)
  {
    printf("Reader not found\n");
    goto done;
  }

  printf("Reader found\n");
  rc = SPROX_ReaderGetDevice(s_buffer, sizeof(s_buffer));
  if (rc == MI_OK)
    printf("Reader found on %s\n", s_buffer);

  rc = SPROX_ReaderGetFirmware(s_buffer, sizeof(s_buffer));
  if (rc == MI_OK)
    printf("Reader firwmare is %s\n", s_buffer);

  rc = SPROX_ReaderGetFeatures(&features);
  if ((rc == MI_OK) && !(features & 0x00000002))
  {
    printf("Warning: this reader is not 15693-enabled\n");
  }

  printf("\n------------------------------\n");


  /* Set RF field to ON */
  SPROX_ControlRF(TRUE);

  printf("Waiting for tags... (Press <Ctrl>+C to exit)\n\n");

  for (;;)
  {
    rc = MI_OK;
    /* Not too often... */
#ifdef WIN32
    if (kbhit())
      break;
    Sleep(50);
#endif
#ifdef __linux
    usleep(5000);
#endif

    for (;;)
    {
      uid_len = sizeof(uid);
      rc = SPROX_Find(PROTO_ANY, &proto, uid, &uid_len);
	  if (rc == MI_NOTAGERR)
        continue;                  /* No more tag (or no tag at all) */

      if (rc != MI_OK)
      {
        printf("\n[Failed]\n");
		printf("  %s (%d)\n", SPROX_GetErrorMessage(rc), rc);
        if (rc < -128)
          goto close;           /* Fatal error */
      }

      if (rc == MI_OK)
	  {
		printf("\nTag found [OK]\n");
		printf("Family=");

		switch (proto)
		{
		  case PROTO_14443_A	: printf("ISO/IEC 14443-A (or NXP Mifare)\n"); break;
		  case PROTO_14443_B	: printf("ISO/IEC 14443-B\n"); break;
		  case PROTO_15693_STD	:
		  case PROTO_15693_FAST	: printf("ISO/IEC 15693\n"); break;
		  case PROTO_ICODE1_STD	:
		  case PROTO_ICODE1_FAST: printf("NXP ICODE-1\n"); break;
		  case PROTO_MEM_PICO	: printf("Inside Contactless PicoTAG\n"); break;
		  case PROTO_MEM_ST		: printf("S.T. MicroElectronics SR\n"); break;
		  case PROTO_MEM_ASK	: printf("ASK CTS256B/CTS512B\n"); break;
		  case PROTO_14443_Bi	: printf("Calypso (Innovatron protocol)\n"); break;
		  case PROTO_EPC		: printf("EPC\n"); break;
		  default				: printf("%04X\n", proto);
		}
    
		printf("UID=");
		for (i=0; i<uid_len; i++)
		  printf("%02X", uid[i]);
		printf("\n");

		break;
	  }
	}

	if (proto == PROTO_14443_A)
	{
      BYTE atq[2];
      BYTE snr[12];
      BYTE snrlen = 12;
      BYTE sak[1];
      WORD w_atq;

      rc = SPROX_A_SelectAny(atq, snr, &snrlen, sak);
      if (rc == MI_OK)
      {
		w_atq = (atq[1] << 8) | atq[0];
		printf("ATQ of ISO 14443-A card is %04X\n", w_atq);

		switch (w_atq)
		{
        
		  case 0x0004 : /* Mifare Classic 1k */
			            printf("Tag appears to be a Mifare Classic 1k\n");
				        break;
		  case 0x0002 : /* Mifare Classic 4k */
                        printf("Tag appears to be a Mifare Classic 4k\n");
                        break;
		  case 0x0044 : /* Mifare UltraLight */
			            printf("Tag appears to be a Mifare UltraLight\n");
				        break;
		  case 0x0344 : /* Desfire */
			            printf("Tag appears to be a Desfire card\n");
				        break;
		  default     : printf("Unsupported ISO 14443-A card (ATQ=%04X)\n", w_atq);
			            if (sak[0] & 0x80)
                        printf("(card is T=CL capable)\n");
		}

		/* Halt currently active tag */
        SPROX_A_Halt();
	  }
	}

	if (proto == PROTO_14443_B)
	{
      BYTE atq_b[11];

      rc = SPROX_B_SelectAny(0x00, atq_b);
      if (rc == MI_OK)
	  {
	    printf("ATQB=");
		for (i = 0; i < 11; i++)
	      printf("%02X", atq_b[i]);
		printf("\n");
	  }

	  /* Halt currently active tag */
  	  SPROX_B_Halt(atq_b);
	}

	if ((proto == PROTO_15693_STD) || (proto == PROTO_15693_FAST))
	{
	  if (proto == PROTO_15693_FAST)
		printf("FAST mode selected\n");

	  switch (uid[1])
	  {
		case 0x04 : /* NXP */
					switch (uid[2])
					{
					  case 0x01 : /* ICODE SLI */
								  printf("Tag appears to be a ICODE SLI\n");
								  break;
					  case 0x03 : /* ICODE SLI-L */
								  printf("Tag appears to be a ICODE SLI-L\n");
								  break;
					  case 0x02 : /* ICODE SLI-S */
								  printf("Tag appears to be a ICODE SLI-S\n");
								  break;
					  default   : /* NXP card */
								  printf("NXP card, unsupported by reader !\n");
								  break;
					}
					break;

		case 0x07 : /* Texas Instrument */
					switch (uid[2] & 0xFE)
					{
					  case 0x00 : /* Tag-it HF-I Plus Inlay */
								  printf("Tag appears to be a Tag-it HF-I Plus Inlay\n");
								  break;
					  case 0x80 : /* Tag-it HF-I Plus Chip */
								  printf("Tag appears to be a Tag-it HF-I Plus Chip\n");
								  break;
					  case 0xC0 : /* Tag-it HF-I Standard Chip/Inlay */
								  printf("Tag appears to be a Tag-it HF-I Standard Chip/Inlay\n");
								  break;
					  case 0xC4 : /* Tag-it HF-I Pro Chip/Inlay */
								  printf("Tag appears to be a Tag-it HF-I Pro Chip/Inlay\n");
								  break;
					  default   : /* Tag-it card */
								  printf("Tag-it card, unsupported by reader !\n");
								  break;
					}
					break;

		case 0x02 : /* STMicroelectronics card*/
					switch ((uid[2] & 0xFC) >> 2)
					{
					  case 0x05 : /* LRI64 */
								  printf("Tag appears to be a ST LRI64\n");
								  break;
					  default   : /* ST card */
								  printf("STMicroelectronics card, unsupported by reader !\n");
								  break;
					}
					break;

		case 0x16 : /* Legic card*/
					printf("Legic card, unsupported by reader !\n");
					break;

		default   : printf("Unsupported ISO 15693\n");
					break;
	  }

	  /* Halt currently active tag */
	  SPROX_Iso15693_Halt();
	}

	if (proto == PROTO_ICODE1_FAST)
	{
	  printf("FAST mode selected\n");
	}
  }

close:
  /* Close the reader */
  SPROX_ControlRF(FALSE);
  SPROX_ReaderClose();

done:
  /* Display last error */
  if (rc == MI_OK)
  {
    printf("Done\n");
  } else
  {
    printf("%s (%d)\n", SPROX_GetErrorMessage(rc), rc);
  }
  return 0;
}
